package com.cy.store.controller;

/**
 * @author Luo Sheng
 * @school YiBin university
 * @create 2022-11-23 21:26
 */

import com.cy.store.controller.ex.*;
import com.cy.store.service.ex.*;
import com.cy.store.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;


/**
 * 控制类的基类
 */
@Slf4j
public class BaseController {
    /**
     * 操作成功的状态码
     */
    protected static final int OK = 200;

    /**
     * 设置文件上传的最大值 10MB
     */
    private static final int AVATAR_MAX_SIZE = 10*1024*1024;

    /**
     * 声明下载文件所在路径
     */
    private static final String AVATAR_PATH = "/upload";

    /**
     * 减少购物车商品数据
     */
    protected static final Integer REDUCE_PRODUCT_NUM = -1;

    /**
     * 增加购物车商品数量
     */
    protected static final Integer ADD_PRODUCT_NUM = 1;


    /**
     * 限制文件的类型
     */
     private static final List<String> AVATAR_TYPE = new ArrayList<>();

    /**
     *  初始化文件类型
     */
    static {
        AVATAR_TYPE.add("image/jpeg");
        AVATAR_TYPE.add("image/png");
        AVATAR_TYPE.add("image/bmp");
        AVATAR_TYPE.add("image/gif");
    }

    /**
     * 请求处理方法，这个方法的返回值就是需要传递给前端的数据
     * @return
     */
    // 自动将异常对象传递给此次方法的参数列表
    // 当前项目中产生的异常，被统一拦截到此方法中，这个方法就充当请求方法的处理方法，方法的返回值直接返回前端
    @ExceptionHandler({ServiceException.class,FileUploadException.class}) // 统一处理抛出的异常
    public JsonResult<Void> handleException(Throwable e){
        // 创建返回前端的对象
        JsonResult<Void> result = new JsonResult<>();

        if (e instanceof UsernameDuplicatedException){
            // 方法执行失败，用户名被占用
            // 设置返回结果的状态以及返回信息
            log.info("用户注册失败，用户名被占用");
            result.setState(4000);
            result.setMessage(e.getMessage());

        }else if (e instanceof UserNotFoundException){
            // 方法执行失败，为查询到用户
            log.info("用户登陆失败，为查询到用户名");
            result.setState(4001);
            result.setMessage(e.getMessage());

        }else if (e instanceof PasswordNotMatchException){
            // 方法执行失败，密码错误
            log.info("用户登陆失败，密码错误");
            result.setState(4002);
            result.setMessage(e.getMessage());

        }else if (e instanceof AddressCountLimitException){
            // 收货地址数超出限制
            log.info("用户收货地址数超出限制");
            result.setState(4003);
            result.setMessage(e.getMessage());

        }else if (e instanceof AddressNotFoundException){
            // 用户收货地址不存在
            log.info("用户收货地址不存在异常");
            result.setState(4004);
            result.setMessage(e.getMessage());
        }else if (e instanceof AccessDeniedException){
            // 用户非法访问收货地址数据异常
            log.info("用户非法访问收货地址数据异常");
            result.setState(4005);
            result.setMessage(e.getMessage());

        }else if (e instanceof ProductNotFoundException) {
            // 商品信息不存在
            log.info("商品信息不存在");
            result.setState(4006);
            result.setMessage(e.getMessage());

        }else if (e instanceof CartNotFoundException) {
            // 购物车信息不存在
            log.info("购物车信息不存在");
            result.setState(4007);
            result.setMessage(e.getMessage());

        }else if (e instanceof NumBreakBoundsException) {
            // 数量越界
            log.info("商品数量越界");
            result.setState(4008);
            result.setMessage(e.getMessage());

        }else if (e instanceof InsertException){
            // 方法执行失败，插入出现未知错误
            log.info("插入方法出现未知错误");
            result.setState(5000);
            result.setMessage(e.getMessage());

        }else if (e instanceof UpdateException){
            // 方法执行失败，更新出现未知异常
            log.info("更新出现未知错误");
            result.setState(5001);
            result.setMessage(e.getMessage());

        }else if (e instanceof DeleteException){
            // 方法执行失败，删除出现未知异常
            log.info("删除出现未知错误");
            result.setState(5002);
            result.setMessage(e.getMessage());

        } else if (e instanceof FileEmptyException) {
            // 文件为空异常
            log.info("上传文件失败，文件为空");
            result.setState(6000);
            result.setMessage(e.getMessage());

        } else if (e instanceof FileSizeException) {
            // 文件尺寸异常
            log.info("上传文件失败，文件尺寸异常");
            result.setState(6001);
            result.setMessage(e.getMessage());

        } else if (e instanceof FileTypeException) {
            // 文件类型异常
            log.info("上传文件失败，文件类型异常");
            result.setState(6002);
            result.setMessage(e.getMessage());

        } else if (e instanceof FileStateException) {
            // 文件状态异常
            log.info("上传文件失败，文件状态异常");
            result.setState(6003);
            result.setMessage(e.getMessage());

        } else if (e instanceof FileUploadIOException) {
            // 文件上传I/O异常
            log.info("上传文件失败，文件I/O异常");
            result.setState(6004);
            result.setMessage(e.getMessage());

        }
        return result;
    }

    /**
     * 获取当前登陆用户的uid
     * @param session
     * @return
     */
    protected final Integer getUidFromSession(HttpSession session){
        return Integer.valueOf(session.getAttribute("uid").toString());
    }

    /**
     * 获取当前用户的username
     * @param session
     * @return
     */
    protected final String getUsernameFromSession(HttpSession session){
        return session.getAttribute("username").toString();
    }

    /**
     * 上传文件
     * @param file
     * @return
     */
    protected final String upload(MultipartFile file,HttpSession session){
        // 判断文件是否为空
        if (file == null){
            throw new FileEmptyException("文件为空");
        }

        // 判断文件大小是否超出限制
        if (file.getSize() > AVATAR_MAX_SIZE){
            throw new FileSizeException("文件大小超出限制");
        }

        // 判断文件的类型是否是规定的后缀类型
        String contentType = file.getContentType();
        if (!AVATAR_TYPE.contains(contentType)){
            throw new FileTypeException("文件类型不支持");
        }

        // 获取文件要上传到服务器的真实路径
        String realPath = session.getServletContext().getRealPath(AVATAR_PATH);
//        String realPath = AVATAR_PATH;

        // 如果没有就创建根据该路径创建文件
        File fileDir = new File(realPath);
        if (!fileDir.exists()){
            fileDir.mkdir(); // 创建当前路径
        }

        // 获取上传文件的后缀名
        String oldFilename = file.getOriginalFilename();
        String suffix = oldFilename.substring(oldFilename.lastIndexOf("."));

        // 生成新的文件名，使用UUID来生成一个新的文件名前缀
        String newFilename = UUID.randomUUID().toString().toUpperCase(Locale.ROOT) + suffix;

        // 创建要以新文件名命名的文件
        File newFile = new File(fileDir, newFilename);

        // 将参数file中的数据写入到这个文件中
        try {
            file.transferTo(newFile);
        }catch (FileStateException e){
            // 抛出文件状态异常
            throw new FileStateException("文件状态异常");
        }
        catch (IOException e) {
            // 抛出文件读写异常
            throw new FileUploadIOException("文件读写异常");
        }

        // 返回头像的路径/upload/filename
        String avatarDir = AVATAR_PATH + "/" + newFilename;

        // 返回存储路径
        return avatarDir;

    }


}
